const generate = require("../utils/generate");

const Op = require("sequelize").Op;
const sequelize = require("../database/index");

/**
 * 获取单条或多条数据
 * @param {*} req 请求信息
 * @param {*} res 响应信息
 * @param {*} next next函数
 * @param {BaseModule} Module 数据模型
 * @param {Object} optionalParam 可选对象
 * @param {string[]} fuzzy 需要模糊查询的字段
 * @param {String} mode 获取一条数据还是多条数据 "single"|"multiple"
 * @param {Number} pageSize 获取多条数据时，每次获取的条数
 */
async function getData(
  req,
  res,
  next,
  Module,
  optionalParam = {
    workMode: "normal",
    fuzzy: null,
    mode: "single",
    pageSize: null,
    mysqlQueryParam: {}, // 其他配置参数
  }
) {
  try {
    const queryParam = req.query;

    // console.log("查询参数为", queryParam);
    // result 目前是由模型对象的实例组成的数组
    const searchParam = {
      ...queryParam,
    };

    // 模糊查询配置字段 --start
    optionalParam?.fuzzy?.forEach((item) => {
      if (queryParam.hasOwnProperty(item)) {
        searchParam[item] = {
          [Op.like]: "%" + queryParam[item] + "%",
        };
      }
    });
    // end

    // 获取多条或分页数据时，需要配置的参数 --start
    const multipleParams = {};
    if (optionalParam?.mode == "multiple") {
      const currentPage = queryParam.pages || generate.generateRandom(10, 1);
      const offset = (optionalParam.pageSize || 10) * (currentPage - 1);

      multipleParams.offset = offset;
      multipleParams.limit = optionalParam.pageSize || 10;
    }
    // --end

    // 查询逻辑 --start
    let result = await Module.findAll({
      // attributes: ["book_name", "author"],
      ...optionalParam?.mysqlQueryParam,
      ...multipleParams,
      where: searchParam,
    });
    if (optionalParam.workMode == "return") {
      return result.map((item) => {
        return item.toJSON();
      });
    } else {
      // 转成josn数据返回至客户端
      result = result.map((item) => {
        return item.toJSON();
      });
      res.status(200).json({
        msg: "查询数据成功",
        info: result,
      });
    }

    // end
  } catch (error) {
    next({ msg: "controller-查询数据库中数据出错", error });
  }
}

async function getDataByOriginalSQL(
  req,
  res,
  next,
  config = {
    targetTableName: "books",
    targetSearchCondition: "book_id",
    dependTableName: "booklist",
  }
) {
  try {
    // 1. 获取传过来的参数
    const query = req.query;
    let { book_list_id, book_list_name } = query;
    // 通过原生的SQL语句进行子查询;
    // const queryParams = "book_id,book_name,author,publisher,place,price";

    const [books] = await sequelize.query(
      `SELECT * from books WHERE book_id IN(SELECT book_id FROM booklist WHERE book_list_id='${book_list_id}')`
    );

    const queryResult = {
      book_list_name,
      book_list_id,
      books: books,
    };
    // 处理数据
    (function (dataList) {
      dataList.forEach((item) => {
        if (item.tag) {
          item.tag = item.tag.split("-");
        }
      });
    })(books);

    res.status(200).json({
      msg: "查询成功",
      queryResult,
    });
  } catch (error) {
    next({ msg: "controller-查询数据库中数据出错", error });
  }
}

// 增加一条记录
async function addRecord(req, res, next, Module) {
  try {
    const data = await Module.create(req.body);
    res.status(201).json({
      msg: "增加数据成功",
      info: data,
    });
  } catch (error) {
    next({ msg: "controller-增加数据至数据库出错", error });
  }
}

// 修改一条记录
async function alter(
  req,
  res,
  next,
  Module,
  config = {
    searchParam: [],
    alterParam: [],
  }
) {
  try {
    const searchParams = {};
    const alterParam = config?.alterParam;

    config?.searchParam.forEach((item) => {
      searchParams[item] = req.body[item];
    });
    const data = await Module.findOne({
      where: {
        ...searchParams,
      },
    });
    // 遍历传过来的对象，基于传过来的对象对数据库进行更改(对data的更改目前还是本地更改)
    alterParam.forEach((key) => {
      data[key] = req.body[key];
    });

    // 把对data的本地更改提交到数据库
    const result = await data.save();

    res.status(201).json({
      msg: "修改成功",
      info: result,
    });
  } catch (error) {
    next({ msg: "controller-更改数据库中数据出错", error });
  }
}

// 改变数量
async function changeNumber(
  req,
  res,
  next,
  Module,
  config = {
    searchParam: [],
    fn: () => {},
  }
) {
  try {
    const searchParams = {};

    config?.searchParam.forEach((item) => {
      searchParams[item] = req.body[item];
    });
    let data = await Module.findOne({
      where: {
        ...searchParams,
      },
    });
    data = config?.fn(data);
    if (!data) {
      return false;
    }

    // 把对data的本地更改提交到数据库
    const result = await data.save();
    return true;
  } catch (error) {
    next({ msg: "controller-更改数据库中数据出错", error });
  }
}

// 删除一条记录
async function del(req, res, next, Module) {
  try {
    let data = await Module.findOne({
      where: {
        ...req.body,
      },
    });
    const result = await data.destroy();
    res.status(200).json({
      msg: "删除成功",
      info: result,
    });
  } catch (error) {
    next({ msg: "controller-从数据库删除数据出错", error });
  }
}

module.exports = {
  getData,
  getDataByOriginalSQL,
  addRecord,
  alter,
  del,
  changeNumber,
};
